/*
 * CodeContextClass.java	 
 *
 * Copyright 2011 Universidad Francisco de Paula Santander (UFPS).
 * Todos los Derechos Reservados.
 * Creado el 07/10/11, 11:23:38 AM
 */

package com.ufps.cuatro.util.generadores.codeobject;

import com.ufps.cuatro.controlador.render.UtilRender;
import com.ufps.cuatro.modelo.representacion.UtilRepresentacion;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.ufps.cuatro.modelo.representacion.componente.Componente;
import com.ufps.cuatro.modelo.representacion.componente.ComponenteDistribuidor;
import com.ufps.cuatro.modelo.representacion.componente.ComponenteDistribuidorContenedor;
import com.ufps.cuatro.modelo.representacion.componente.ComponenteDistribuidorGeneradorUnitario;
import com.ufps.cuatro.modelo.representacion.componente.ComponenteDistribuidorModeloAsociado;

/**
 * <i><b>CodeContextClass:</b></i><p>Esta Clase Representa el Contexto de ejecución
 * para la generación del Código Fuente de las Representaciones Gráficas 
 * Generadas por un Modelo Analizado.</p>
 * 
 * @author Carlos A. Torres C. - Dolly E. Guerrero. <https://code.google.com/p/tesis4dor/>
 * @version 1.0 07/10/11
 * @see     CodeContextType
 * @see     CodeContextGenerateCodeRules
 */
public class CodeContextClass extends CodeContextType implements CodeProcessGenerator, CodeContextGenerateCodeRules{
    private ArrayList<CodeContextMethod> objFunctions;
    /**
     * Constructor que Inicializa el <code>Componente</code> que generará el
     * Código Fuente.
     * @param objComponente <code>Componente</code> que generará el
     * Código Fuente.
     */
    public CodeContextClass(Componente objComponente) {
        super(EnumModificador.ePublic,objComponente);
        init();
    }   

    /**
     * Constructor que Inicializa el <code>Componente</code> que generará el
     * Código Fuente y si Modificador de Acceso (public - protectec - private).
     * @param eModificador Modificador de Acceso (public - protectec - private).
     * @param objComponente <code>Componente</code> que generará el
     * Código Fuente.
     */
    public CodeContextClass(EnumModificador eModificador, Componente objComponente) {
        super(eModificador, objComponente);     
        init();
    }
    
    /**
     * Determina si la Clase Generada debe implementar funciones encpasuladas de tipos de Datos.
     * @return boolean que determina si la Clase Generada debe implementar funciones encpasuladas de tipos de Datos.
     */
    public boolean isDefinedEncapsulateFunctions(){
        try{
            return !objFunctions.isEmpty();
        }catch(java.lang.NullPointerException ex){
            Logger.getLogger(CodeContextClass.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }
    
    public void generateSourceCodeSyntaxFaseImport(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseImport(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseFieldDefinitionInstance(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseFieldDefinitionInstance(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseFieldDefinitionClass(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseFieldDefinitionClass(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseFieldDefinitionConstant(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseFieldDefinitionConstant(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseFieldInitializationInstance(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseFieldInitializationInstance(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseFieldInitializationClass(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseFieldInitializationClass(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseFieldInitializationProperties(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseFieldInitializationProperties(objSourceLinesCode);
        }
    }
        
    public void generateSourceCodeSyntaxjComponentIntoTab(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxjComponentIntoTab(objSourceLinesCode);
        }
    }    
    
    public void generateSourceCodeSyntaxModelAsociateButtonOk(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidorModeloAsociado){
            ComponenteDistribuidorModeloAsociado objComponenteDistribuidor = (ComponenteDistribuidorModeloAsociado) (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxDialogButtonOk(objSourceLinesCode);
        }
    }
    
    
    public void generateSourceCodeSyntaxModelAsociateButtonCancel(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidorModeloAsociado){
            ComponenteDistribuidorModeloAsociado objComponenteDistribuidor = (ComponenteDistribuidorModeloAsociado) (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxDialogButtonCancel(objSourceLinesCode);
        }
    }    
    
    public void generateSourceCodeSyntaxFaseFieldInitializationGridBagConstraints(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseFieldInitializationGridBagConstraints(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseMethodDefinitionEvent(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodDefinitionEvent(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseMethodImplementEvent(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodImplementEvent(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseMethodImplementFunctionEvent(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodImplementEvent(objSourceLinesCode);
        }
    } 
    
    public void generateSourceCodeSyntaxFaseMethodImplementMenuParentEvent(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodImplementMenuParentEvent(objSourceLinesCode);
        }
    }   
    
    public void generateSourceCodeSyntaxFaseMethodDefinitionMenuEvent(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodDefinitionMenuEvent(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseMethodImplementMenuEvent(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodImplementMenuEvent(objSourceLinesCode);
        }
    }
    
    public void generateSourceCodeSyntaxFaseMethodImplementMenuFunctionEvent(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodImplementMenuEvent(objSourceLinesCode);
        }
    }  
    
    public void generateSourceCodeSyntaxFaseMethodImplementFunctionSet(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodImplementFunctionSet(objSourceLinesCode);
        }
    }

    public void generateSourceCodeSyntaxFaseMethodImplementFunctionGet(ArrayList<CodeContextLine> objSourceLinesCode) {
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            objComponenteDistribuidor.generateSourceCodeSyntaxFaseMethodImplementFunctionGet(objSourceLinesCode);
        }
    }
    
    private void init(){
        this.objFunctions = new ArrayList<CodeContextMethod>();
    }
    
    /**
     * Determina si el Componente contiene un Modelo Asociado.
     * @return estado del proceso.
     */
    public boolean isContainsAsociateModel(){
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            for(Componente obj : objComponenteDistribuidor.getComponentesDistribuidos()){
                if(obj instanceof ComponenteDistribuidorGeneradorUnitario){
                    ComponenteDistribuidorGeneradorUnitario objC = (ComponenteDistribuidorGeneradorUnitario) obj;
                    if(objC.getObjModeloAsociado() != null){
                        return true;
                    }
                }
            }
        }            
        return false;
    }
    
    /**
     * Determina si se requiere definir Imports en la Generación del Código Fuente.
     * @return boolean que determina si se requiere definir Imports en la Generación del Código Fuente.
     */
    public boolean isRequieredImportAsociateModel(){
        try{
            return objComponente.isRequiereModeloAsociado();
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole("Componente Nulo", UtilRender.ACTION_ERROR, true);
        }
        return false;
    }
    
    /**
     * Determina si se requiere definir Controles en la Generación del Código Fuente.
     * @return boolean que determina si se requiere definir Controles en la Generación del Código Fuente.
     */
    public boolean isDefinedFields(){
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            return objComponenteDistribuidor.isComponentesDistribuidos();
        }
        return false;
    }
    
    /**
     * Determina si se requiere definir Eventos que se aplican a los Controles en la Generación del Código Fuente.
     * @return boolean que determina si se requiere definir Eventos que se aplican a los Controles en la Generación del Código Fuente.
     */
    public boolean isDefinedEvents(){
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            return objComponenteDistribuidor.isRequiredDefinitionEvents();
        }
        return false;
    } 
    
    public boolean isImplementedMenu(){
        if(objComponente instanceof ComponenteDistribuidorContenedor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            return objComponenteDistribuidor.hasMenuAvailable();
        }
        return false;
    }
    
    public ArrayList<CodeContextLine> generateSourceCodeSyntaxString(String strEnumTypeCodeSyntax){
        try{
            this.getObjSentences().remove(strEnumTypeCodeSyntax);
            EnumTypeCodeSyntax eTypeCodeSyntax = EnumTypeCodeSyntax.valueOf(strEnumTypeCodeSyntax);            
            return generateSourceCodeSyntax(eTypeCodeSyntax);
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole("Valor de Enumeración Nulo", ex.getMessage(), UtilRender.ACTION_ERROR);
        }
        return null;
    }    
    
    public CodeContextLine generateSingleSourceCodeSyntax(String strEnumTypeCodeSyntax){
        try{
            EnumTypeCodeSyntax eTypeCodeSyntax = EnumTypeCodeSyntax.valueOf(strEnumTypeCodeSyntax);
            return generateSingleSourceCodeSyntax(eTypeCodeSyntax);
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole("Valor de Enumeración Nulo", ex.getMessage(), UtilRender.ACTION_ERROR);
        }
        return null;
    }

    public ArrayList<CodeContextLine> generateSourceCodeSyntax(EnumTypeCodeSyntax eTypeCodeSyntax) {
        try{
            ArrayList<CodeContextLine> objSourceLinesCode = new ArrayList<CodeContextLine>();        
            //---------------------------------------------------------------------/
            //Generación de Código por Fases.
            //---------------------------------------------------------------------/
            if(isValidRule(eTypeCodeSyntax, (ComponenteDistribuidor)objComponente) && eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseImport){
                generateSourceCodeSyntaxFaseImport(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseFieldDefinitionInstance){
                generateSourceCodeSyntaxFaseFieldDefinitionInstance(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseFieldDefinitionClass){
                generateSourceCodeSyntaxFaseFieldDefinitionClass(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseFieldDefinitionConstant){
                generateSourceCodeSyntaxFaseFieldDefinitionConstant(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseFieldInitializationInstance){
                generateSourceCodeSyntaxFaseFieldInitializationInstance(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseFieldInitializationClass){
                generateSourceCodeSyntaxFaseFieldInitializationClass(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseFieldInitializationProperties){
                generateSourceCodeSyntaxFaseFieldInitializationProperties(objSourceLinesCode);
            }                    
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodDefinitionEvent){
                generateSourceCodeSyntaxFaseMethodDefinitionEvent(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseFieldInitializationGridBagConstraints){
                generateSourceCodeSyntaxFaseFieldInitializationGridBagConstraints(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodImplementEvent){
                generateSourceCodeSyntaxFaseMethodImplementEvent(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodImplementFunctionEvent){
                generateSourceCodeSyntaxFaseMethodImplementFunctionEvent(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodImplementGetFunction){
                this.generateSourceCodeSyntaxFaseMethodImplementFunctionGet(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodImplementSetFunction){
                this.generateSourceCodeSyntaxFaseMethodImplementFunctionSet(objSourceLinesCode);
            }
            //------------------------------------------------------------------
            // Definición de Casos Especiales de Generación de Código Fuente.
            //------------------------------------------------------------------
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseInitializationTab){//solo plantilla tab
                generateSourceCodeSyntaxjComponentIntoTab(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseDialogModelAsociateButtonOK){//solo modelo asociado
                generateSourceCodeSyntaxModelAsociateButtonOk(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseDialogModelAsociateButtonCancel){//solo modelo asociado
                generateSourceCodeSyntaxModelAsociateButtonCancel(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodDefinitionMenuParentEvent){
                generateSourceCodeSyntaxFaseMethodImplementMenuParentEvent(objSourceLinesCode);
            }            
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodDefinitionMenuEvent){
                generateSourceCodeSyntaxFaseMethodDefinitionMenuEvent(objSourceLinesCode);
            }            
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodImplementMenuEvent){
                generateSourceCodeSyntaxFaseMethodImplementMenuEvent(objSourceLinesCode);
            }
            else if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseMethodImplementFunctionMenuEvent){
                generateSourceCodeSyntaxFaseMethodImplementMenuFunctionEvent(objSourceLinesCode);
            }
            return objSourceLinesCode;
        }catch(java.lang.NullPointerException ex){
            UtilRender.printlnConsole("Error Null", ex.getMessage(), UtilRender.ACTION_ERROR);
        }
        return null;
    }        
    
    
    public CodeContextLine generateSingleSourceCodeSyntax(EnumTypeCodeSyntax eTypeCodeSyntax) {        
        return null;
    }    

    /**
     * Devuelve las Funciones definidas en el Contexto de Generación Actual.
     * @return Colección de Funciones.
     */
    public ArrayList<CodeContextMethod> getObjFunctions() {
        return objFunctions;
    }
    
    /**
     * Adiciona una Definición de Funcion.
     * @param objCodeContextMethod Definición de Función en el Contexto de Código.
     * @return boolean que determina el resultado de la adición.
     */
    public boolean addFunctions(CodeContextMethod objCodeContextMethod){
        return objFunctions.add(objCodeContextMethod);        
    }

    public boolean isValidRule(EnumTypeCodeSyntax eTypeCodeSyntax, ComponenteDistribuidor objComponenteDistribuidor) {
        if(eTypeCodeSyntax == EnumTypeCodeSyntax.eFaseImport && (objComponenteDistribuidor instanceof ComponenteDistribuidor)){
            return false;
        }
        return true;
    }
    
    /**
     * Determina si la Representación Actual tiene definido un Paquete.
     * @return boolean que determina si existe un Paquete asociado.
     */
    public boolean isDefinedPackage(){
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            return objComponenteDistribuidor.getStrPaquete() == null ? false : true;
        }
        return false;
    }
    
    /**
     * Devuelve la Definición del Paquete que contiene la Representación.
     * @return Definición del Paquete.
     */
    public String getObjPackage(){
        if(objComponente instanceof ComponenteDistribuidor){
            ComponenteDistribuidor objComponenteDistribuidor = (ComponenteDistribuidor) objComponente;
            return objComponenteDistribuidor.getObjPackage();
        }
        return "package" + UtilRepresentacion.strPackageRootGUI + ";";
    }

    
}
